package com.framework.file.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.framework.common.exception.BusinessException;
import com.framework.file.dto.FileManageUploadDto;
import com.framework.file.dto.SysFileDto;
import com.framework.file.mapper.FileManageMapper;
import com.framework.file.model.FileManage;
import com.framework.file.param.FileManageParam;
import com.framework.file.repository.FileManageRepository;
import com.framework.file.repository.SysFileRepository;
import com.framework.file.service.IFileManageService;
import com.framework.file.service.ISysFileService;
import com.framework.file.util.ToolUtils;
import com.framework.file.vo.FileManageVo;
import com.framework.file.vo.SysDeptVo;
import com.framework.file.vo.SysUserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;


/**
 * @description: 档案管理 Service
 * @author: lizurong
 * @version: 1.0
 * @date: 2021-04-01 16:53:14
 */
@Service
@Transactional
public class FileManageService implements IFileManageService {
    @Autowired
    private FileManageMapper baseMapper;

    @Autowired
    private FileManageRepository baseRepo;

    @Autowired
    private ISysFileService sysFileService;

    @Autowired
    private SysFileRepository sysFileRepository;

    @Override
    public Page<FileManage> listPage(FileManageParam param, PageRequest pageRequest) {
        Page<FileManage> page = baseMapper.listPage(param, pageRequest);
        for (FileManage fileManage : page.getContent()) {
            SysUserVo sysUserVo = baseMapper.getByUserId(fileManage.getCreaterId());
            fileManage.setCreaterName(sysUserVo.getName());
            fileManage.setFile(sysFileRepository.findOne(fileManage.getFileId()));
        }
        return page;
    }

    @Override
    public String save(FileManage param) {
        FileManage pEntity = baseRepo.findOne(param.getPid());
        FileManage dbEntity = baseRepo.getTopByFolderName(param.getFolderName());
        if (dbEntity != null && dbEntity.getPid().equals(param.getPid())) {
            throw new BusinessException("文件夹名称重复!");
        }
        if (pEntity == null) {
            param.setTreeLevel(0);
        } else {
            param.setTreeLevel(pEntity.getTreeLevel() + 1);
        }
        param.setCreateTime(new Date());
        param.setUpdateTime(new Date());
        baseRepo.save(param);
        return param.getId();
    }

    @Override
    public void delete(List<String> ids) {
        String[] arr = new String[ids.size()];
        baseRepo.deleteById(ids.toArray(arr));
    }

    @Override
    public void update(FileManage param) {
        FileManage entity = baseRepo.findOne(param.getId());
        boolean updatedFolderName = false;//标识是否修改了文件夹名称
        if (!entity.getFolderName().equals(param.getFolderName())) {
            updatedFolderName = true;
        }
        // 复制其他入参到数据中
        entity.setFolderName(param.getFolderName());
        entity.setSavePeriod(param.getSavePeriod());
        entity.setIsComplete(param.getIsComplete());
        entity.setDescription(param.getDescription());
        BeanUtils.copyProperties(param, entity, "id");
        baseRepo.save(entity);
        if (updatedFolderName) {
            //同步更新该文件夹下文件模块的名称
            List<FileManage> fileManageList = baseRepo.getTopTree(param.getId());
            for (FileManage fileManage : fileManageList) {
                fileManage.setFolderName(param.getFolderName());
                baseRepo.save(fileManage);
            }
        }
    }

    @Override
    @Transactional
    public List<FileManageVo> getLeftList(String loginComId) {
        //根据当前登录人公司去查该企业及其子公司企业 档案列表
        List<FileManage> topList = baseMapper.getFileManageComList(loginComId);
        List<FileManageVo> voList = Lists.newArrayList();
        for (FileManage fileManage : topList) {
            FileManageVo vo = new FileManageVo();
            SysDeptVo sysDeptVo = baseMapper.getDeptByComId(fileManage.getId());
            vo.setComId(sysDeptVo.getCompanyId());
            vo.setComName(sysDeptVo.getFullname());
            vo.setFileManageId(fileManage.getId());
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public String getTreeLocation(String id) {
        LinkedList<String> pFolderNameList = Lists.newLinkedList();
        FileManage fileManage = baseRepo.findOne(id);
        if (fileManage == null) throw new BusinessException("档案管理节点获取失败，请联系管理员!");
        pFolderNameList.add(fileManage.getFolderName());
        if (fileManage.getTreeLevel() > 0) {
            this.treeParentRec(fileManage, pFolderNameList);
        }
        Collections.reverse(pFolderNameList);
        return StringUtils.join(pFolderNameList, "/");
    }

    @Override
    @Transactional
    public List<FileManage> getTree(String id) {
        FileManage fileManage = baseRepo.findOne(id);
        List<FileManage> topList = baseRepo.getTopTree(id);
        //只取出不含文件的目录
        List<FileManage> childAllList = baseMapper.getChildTreeNoFile(fileManage.getId());
        if (ToolUtils.isNotEmpty(childAllList)) {
            //过滤条件set，指定set预期大小为非顶级类目集合的size
            Set<String> set = Sets.newHashSetWithExpectedSize(childAllList.size());
            //循环顶级类目插入子类目
            topList.forEach(top -> getChild(top, childAllList, set));
            return topList;
        }
        return topList;
    }

    @Override
    public void upload(FileManageUploadDto dto) throws Exception {
        FileManage pFile = baseRepo.findOne(dto.getPid());
        if (pFile == null) throw new BusinessException("未查询到id为：" + dto.getPid() + "数据");
        FileManage fileManage = new FileManage(pFile.getId(), pFile.getTreeLevel() + 1, pFile.getFolderName(), dto.getSavePeriod(), dto.getIsComplete(), dto.getDescription(), dto.getSource(), dto.getPaperLocation(), dto.getTag());
        MultipartFile file = dto.getMultipartFile();

        SysFileDto sysFileDto = SysFileDto.builder();
        sysFileDto.setExt(org.springframework.util.StringUtils.getFilenameExtension(file.getOriginalFilename()));
        sysFileDto.setSize(file.getSize());
        sysFileDto.setAuthor(dto.getCreaterId());
        sysFileDto.setModule("fileManage");

        //  将文件上传到fastdfs服务器
        String newFileId = sysFileService.upload(sysFileDto);
        fileManage.setFileId(newFileId);
        fileManage.setCreaterId(dto.getCreaterId());
        fileManage.setCreateTime(new Date());
        fileManage.setUpdateTime(new Date());
        baseRepo.save(fileManage);//保存档案管理
    }

    @Override
    @Transactional
    public void initSgCatalog() throws Exception {
        List<SysDeptVo> sgDeptList = baseMapper.getSysDeptListByComId("4028817c7868f8f0017868f9e53d0001");
        for (SysDeptVo sysDeptVo : sgDeptList) {
            String[] folderNames = {"工程管理文件", "施工准备文件", "施工质量控制文件", "竣工图", "声像资料", "其他"};
            Map<String, String> secondMap = new HashMap<>();//定义二级目录map
            String pid = baseRepo.getIdByPid(sysDeptVo.getId());
            for (String folderName : folderNames) {
                FileManage entity = new FileManage();
                entity.setPid(pid);
                entity.setFolderName(folderName);
                String secondId = this.save(entity);
                secondMap.put(folderName, secondId);
            }
            Map<String, String> thirdMap = new HashMap<>();//定义三级目录map
            //init二级目录
            secondMap.forEach((k, v) -> {
                String[] folderNames2 = {};
                if (k.equals("施工准备文件")) {
                    folderNames2 = new String[]{"开工申请文件", "技术交底图纸会审", "开工前测量文件"};
                } else if (k.equals("施工质量控制文件")) {
                    folderNames2 = new String[]{"工程及设计变更", "施工日志、大事记", "永久性水准点坐标图", "试验报告", "各项目标准及工艺试验资料", "工地试验室管理文件",
                            "原材料质保文件", "工程质量评定文件", "施工原始文件"};
                } else if (k.equals("声像资料")) {
                    folderNames2 = new String[]{"重大活动、事故处理资料", "隐蔽工程施工"};
                } else if (k.equals("工程管理文件")) {
                    folderNames2 = new String[]{"人员管理"};
                }
                for (String folderName2 : folderNames2) {
                    FileManage entity = new FileManage();
                    entity.setPid(v);
                    entity.setFolderName(folderName2);
                    try {
                        String thirdId = this.save(entity);
                        if (ToolUtils.in(folderName2, "施工原始文件", "工程及设计变更", "施工日志、大事记")) {
                            thirdMap.put(folderName2, thirdId);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            //init 三级目录
            thirdMap.forEach((k, v) -> {
                String[] folderNames3 = {};
                if (k.equals("施工原始文件")) {
                    folderNames3 = new String[]{"单位、分部、分项工程开工批准文件", "试验检测报验文件", "隐蔽工程验收记录", "混凝土配合比设计报告、配料单",
                            "砂浆试验检测报告及汇总", "预应力张拉、压浆检查记录", "桩基检测报告", "机电、监控设备安装调试及性能考核记录", "桥隧工程风险评估报告、专项施工技术方案",
                            "事故情况及调查处理报告", "施工中遇到非正常情况记录、处理方案及观察记录，对工程质量影响分析"};
                } else if (k.equals("工程及设计变更")) {
                    folderNames3 = new String[]{"变更申请编号"};
                } else if (k.equals("施工日志、大事记")) {
                    folderNames3 = new String[]{"施工日志", "施工安全日志"};
                }
                for (String folderName3 : folderNames3) {
                    FileManage entity = new FileManage();
                    entity.setPid(v);
                    entity.setFolderName(folderName3);
                    try {
                        this.save(entity);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    @Override
    public void initJlCatalog() throws Exception {

    }

    @Override
    public void initYzCatalog() throws Exception {

    }

    public void getChild(FileManage fileManage, List<FileManage> fileManageList, Set<String> set) {
        List<FileManage> childlist = Lists.newArrayList();
        fileManageList.stream()
                //判断是否已循环过当前对象
                .filter(c -> !set.contains(c.getId()))
                //判断是否父子关系
                .filter(c -> c.getPid().equals(fileManage.getId()))
                //set集合大小不超过contractList的大小
                .filter(c -> set.size() <= fileManageList.size())
                .forEach(c -> {
                    //放入set，递归循环时可以跳过这个子类目，提高循环效率
                    set.add(c.getId());
                    //获取当前类目的子类目
                    getChild(c, fileManageList, set);
                    //加入子类目集合
                    childlist.add(c);
                });
        fileManage.setChildren(childlist);
    }

    /**
     * 根据子类递归出 所有所属父类
     */
    private void treeParentRec(FileManage fileManage, LinkedList<String> strList) {
        FileManage pFileManage = baseRepo.findOne(fileManage.getPid());
        strList.add(pFileManage.getFolderName());
        if ("isCom".equals(pFileManage.getDescription())) return;
        //递归遍历上一级
        this.treeParentRec(pFileManage, strList);
    }

}
